import { useState, useEffect, useRef } from "react";

// 如果传入{key:false}时也会返回true，然后后续就会被删除，这不是我们想要的
export const isFalsy = (value: unknown) => (value === 0 ? false : !value);

export const isVoid = (value: unknown) =>
  value === undefined || value === null || value === "";

// 在一个函数里，改变传入的对象本身是不好的
export const cleanObject = (object: { [key: string]: unknown }) => {
  const result = { ...object };
  Object.keys(result).forEach((key) => {
    // 这里涉及到泛型的知识，先不处理
    const value = result[key];

    // 排除0的情况
    if (isVoid(value)) {
      delete result[key];
    }
  });
  return result;
};

export const useMount = (callback: () => void) => {
  useEffect(() => {
    callback();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
};

// 返回用泛型来规范类型，debouncedValue 的类型需要跟着 value 的类型变化
export const useDebounce = <T>(value: T, delay?: number): T => {
  const [debouncedValue, setDebouncedValue] = useState(value);

  // 在value或delay变化时执行这个effect
  useEffect(() => {
    // effect中设置一个定时器，用来更新debounceValue的值
    const timeout = setTimeout(() => setDebouncedValue(value), delay);

    // 每次在上一次useEeffect执行完之后被执行，一般负责清理的作用
    // 返回的函数用来清除一些副作用
    return () => clearTimeout(timeout);
  }, [value, delay]);

  return debouncedValue;
};

export const useArray = <T>(list: T[]) => {
  const [value, setValue] = useState(list);

  const add = (user: T) => setValue([...value, user]);

  const removeIndex = (index: number) => {
    const list = [...value];
    list.splice(index, 1);
    setValue(list);
  };

  const clear = () => setValue([]);

  return { value, setValue, clear, removeIndex, add };
};

// 希望在进入项目列表时加载显示项目列表，退出时显示原来的列表名称"React App"
export const useDocumentTitle = (
  title: string,
  keepOnUnmount: boolean = true
) => {
  // const oldTitle = document.title;

  // 使用useRef在初始化时把值保存起来，它就像一个容器，保持着这个值在整个组件的生命周期中都不会被改变
  const oldTitle = useRef(document.title).current;

  useEffect(() => {
    document.title = title;
  }, [title]);

  useEffect(() => {
    return () => {
      if (!keepOnUnmount) {
        console.log("卸载时title", oldTitle);
        // 如果useEffect不指定依赖，oldTitle一直都是oldTitle==='React App'
        // 当加上oldTitle依赖时，这里的值就是最新的oldTitle==='项目列表'，那么就无法保留旧的oldTitle
        // 但是可以使用react自带的hook--useRef
        document.title = oldTitle;
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [keepOnUnmount, oldTitle]);
};

export const resetRoute = () => (window.location.href = window.location.origin);
